package multimedia.view;

import java.awt.Dimension;
import java.io.File;
import java.io.FilenameFilter;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Scanner;
import java.util.Vector;

import magick.MagickException;
import multimedia.model.DWT;
import multimedia.model.Histogram;
import multimedia.model.ImageCell;
import multimedia.model.ModifiedImage;
import multimedia.model.colorspace.ColorspaceInterface;
import multimedia.model.colorspace.ColorspaceUtil;
import multimedia.model.quantize.MedianCut;
import multimedia.util.DatabaseInterfacer;
import multimedia.util.ProjectConstants;

/**
 * Given a set of images and an input image it'll output the 5 images that match the best in order.
 * 
 * @author trigueros
 * 
 */
public class PhaseIII
{
    private static int DIM = 512;

    public static void main( String[] args )
    {
        // Delete config files if they exist.
        new File( ProjectConstants.IMAGE_DB + ProjectConstants.DWT_DB ).delete();
        new File( ProjectConstants.IMAGE_DB + ProjectConstants.HIST_DB ).delete();
        new File( ProjectConstants.IMAGE_DB + ProjectConstants.HISTSPEC_DB ).delete();
        
        // Application Variables
        ModifiedImage queryImage = null;
        int m = 0, n = 0;

        // Takes user input from System.in
        Scanner input = new Scanner(System.in);

        // Ask user to input the image that they want to compare.
        System.out.print("Enter Query Image: ");
        try
        {
             queryImage = new ModifiedImage( input.nextLine() );
//            queryImage = new ModifiedImage(ProjectConstants.IMAGE_DIR + "lena.png");
            
            // Scale
            queryImage.scaleImage(DIM, DIM);
            
            // Convert to YIQ
            queryImage.getImagePixelHolder().setRgbVector( ColorspaceUtil.ConvertToYIQ( queryImage.getImagePixelHolder().getRgbVector() ) );
            

        } catch ( MagickException e )
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        // Ask for n and m values
        System.out.print("Enter the number of m significant values: ");
         m = input.nextInt();
        System.out.print("Enter the number of n significant values: ");
         n = input.nextInt();

        System.out.println("Starting Query to Database");

        List<String> databaseFilenames = Arrays.asList((new File(ProjectConstants.IMAGE_DB)).list(new FilenameFilter() {

            @Override
            public boolean accept( File dir, String name )
            {
                return name.endsWith(".png") || name.endsWith(".jpg");
            }
        }));
        
        // Set the amount of pictures in the DB
        DatabaseInterfacer.databaseImageCount = databaseFilenames.size();

        // Sort the list and this will be our image index
        Collections.sort(databaseFilenames);

        // Create a vector of modified images
        Vector<ModifiedImage> databaseImages = new Vector<ModifiedImage>();

        // Popuplate the Vector
        System.out.print("Reading Database Images");
        for ( int i = 0; i < databaseFilenames.size(); i++ )
        {
            try
            {
                // Read Image
                ModifiedImage currentImage = new ModifiedImage(ProjectConstants.IMAGE_DB + databaseFilenames.get(i));

                // Scale Image
                currentImage.scaleImage(DIM, DIM);

                // Convert to YIQ
                currentImage.getImagePixelHolder().setRgbVector( ColorspaceUtil.ConvertToYIQ( currentImage.getImagePixelHolder().getRgbVector() ) );

                // Add image to Vector
                databaseImages.add(currentImage);
                System.out.print(".");
            } catch ( MagickException e )
            {
                e.printStackTrace();
            }
        }
        
        // Preping for Histrogram Specification
        ModifiedImage collectedPixels = new ModifiedImage();
        System.out.print("\nCollecting Pixels from Database");
        for( int i = 0; i < databaseImages.size(); i++ )
        {
            Vector<ColorspaceInterface> currentVector = databaseImages.get(i).getImagePixelHolder().getRgbVector();
            Vector<ColorspaceInterface> accumulatedVector = collectedPixels.getImagePixelHolder().getRgbVector();
            accumulatedVector.addAll(currentVector);
            System.out.print(".");            
        }
        // Needed to do this HACK so that median cut worked.
        collectedPixels.setImageSize( new Dimension(DIM, DIM*databaseImages.size()));
        
        // Creating Histogram Specification
        System.out.println("\nCreating Histogram Specification");
        MedianCut medianCut = new MedianCut(collectedPixels);
        medianCut.MedianCutAlgorithm(); 
        
        // Breaking off into 8x8 blocks
        for( int i = 0; i < databaseImages.size(); i++ )
        {
            // Divide Image
            System.out.println("Image ID " + i +": Splitting into 8x8");
            // TODO: This
            Vector<ImageCell> imageCells = ImageCell.divideImage(databaseImages.get(i));
            
            // Create histogram for image.
            System.out.print("Creating Image Histograms");
            for( int bin = 0; bin < imageCells.size(); bin++ )
            {
                // TODO: Histogram needs to be fixed.
//                Histogram currentHist = new Histogram(i, imageCells.get(bin));
//                DatabaseInterfacer.WriteToDatabase(ProjectConstants.IMAGE_DB + "imageHistograms.txt", currentHist.getHistogramStrings());
//                System.out.print(".");
            }
            
            // TODO:Applying DCT
            System.out.println("\nApplying DCT");
        }
        
        // Applying 2D DWT
        System.out.print("Obtaining DWT Significant Components");
        for( int i = 0; i < databaseImages.size(); i++ )
        {
            DWT haarTransform = new DWT(databaseImages.get(i));
            haarTransform.applyTransform();
            haarTransform.generateFileOutput(ProjectConstants.IMAGE_DB + ProjectConstants.DWT_DB, i, m);
            System.out.print(".");
        }
        
        System.out.println("\nCompleted Creating Database Data!\n");
        
        // Analyze Query Image
        System.out.println("Analyzing Query Image and Finding Best Matches");
        
        // Split Query image into 8x8
        Vector<ImageCell> queryImageCells = ImageCell.divideImage(queryImage);
        
        // TODO: Create a histogram for queryImage
        
        // TODO: Create a DCT data for queyrImage
        
        // Create DWT data for queryImage
        DWT haarTransform = new DWT(queryImage);
        haarTransform.applyTransform();
//        haarTransform.generateFileOutput(queryImage.getOriginalFilename() + "DWT.txt", -1, m);
        
        
        // TODO: Obtain color matches
        
        // TODO: Obtain DCT matches
        
        // Obtain DWT matches
        Vector<Integer> index = DWT.ObtainMatches( haarTransform, ProjectConstants.IMAGE_DB + ProjectConstants.DWT_DB);
        System.out.println("\n\nDWT Matches:");
        for ( Integer i : index )
        {
            System.out.println(databaseFilenames.get(i));
        }

    }

}
